﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Uniforax.Battlefield.Input;
using Uniforax.Battlefield.Interfaces;
using Uniforax.Battlefield.UI;

namespace Uniforax.Battlefield
{
    public class UniforaxGame : Game, IAceeptRoutedInput
    {
        private SpriteBatch _spriteBatch;

        private GraphicsDeviceManager _graphicsDeviceManager;

        private Texture2D _testImageTexture;

        private ButtonState _lastButtonState;

        private TestButton _button;

        public UniforaxGame()
        {
            _graphicsDeviceManager = new GraphicsDeviceManager(this);
        }

        protected override void Initialize()
        {
            _button = new TestButton(this);
            Components.Add(_button);
            base.Initialize();
            IsMouseVisible = true;
        }

        protected override void LoadContent()
        {
            base.LoadContent();
        }

        protected override void Update(GameTime gameTime)
        {
            //DoInputReverse(this);
            //DoInput(this);

            var buttonState = Mouse.GetState();

            if (MouseManager.CaptureObject is null)
            {
                DoOnMouseLeftButtonDown(new MouseRoutedEventArgs(buttonState), this);
                DoOnMouseLeftButtonUp(new MouseRoutedEventArgs(buttonState), this);
                DoOnMouseMove(new MouseRoutedEventArgs(buttonState), this);
            }
            else
            {
                DoOnMouseLeftButtonDown(new MouseRoutedEventArgs(buttonState), this);
                DoOnMouseLeftButtonUpCaptured(new MouseRoutedEventArgs(buttonState), this);
                DoOnMouseMoveCaptured(new MouseRoutedEventArgs(buttonState), this);
            }

            _button.BoardSize = new Vector2(buttonState.X, buttonState.Y);

            base.Update(gameTime);
            _lastButtonState = buttonState.LeftButton;
        }

        private void DoInputReverse(IAceeptRoutedInput parent)
        {
            var eventArgs = new Input.RoutedEventArgs();
            foreach (var item in parent.GetInputChildren())
            {
                item.HandleInput(eventArgs);
                if (eventArgs.IsHandled) break;
                DoInputReverse(item);
                if (eventArgs.IsHandled) break;
            }
        }

        private void DoInput(IAceeptRoutedInput parent)
        {
            var eventArgs = new Input.RoutedEventArgs();
            foreach (var item in parent.GetInputChildren())
            {
                DoInputReverse(item);
                if (eventArgs.IsHandled) break;
                item.HandleInput(eventArgs);
                if (eventArgs.IsHandled) break;
            }
        }


        private void DoOnMouseLeftButtonDown(MouseRoutedEventArgs eventArgs, IAceeptRoutedInput parent)
        {
            if (_lastButtonState == ButtonState.Released && eventArgs.MouseState.LeftButton == ButtonState.Pressed)
            {
                foreach (var item in parent.GetInputChildren())
                {
                    DoOnMouseLeftButtonDown(eventArgs, item);
                    if (eventArgs.IsHandled) break;
                    if (item.HitTest(eventArgs.MousePos))
                    {
                        item.OnMouseLeftButtonDown(eventArgs);
                        if (eventArgs.IsHandled) break;
                        return;
                    }
                }
            }
        }

        private void DoOnMouseLeftButtonUp(MouseRoutedEventArgs eventArgs, IAceeptRoutedInput parent)
        {
            if (_lastButtonState == ButtonState.Pressed && eventArgs.MouseState.LeftButton == ButtonState.Released)
            {
                foreach (var item in parent.GetInputChildren())
                {
                    DoOnMouseLeftButtonUp(eventArgs, item);
                    if (eventArgs.IsHandled) break;
                    if (item.HitTest(eventArgs.MousePos))
                    {
                        item.OnMouseLeftButtonUp(eventArgs);
                        if (eventArgs.IsHandled) break;
                        return;
                    }

                }
            }
        }

        private void DoOnMouseLeftButtonUpCaptured(MouseRoutedEventArgs eventArgs, IAceeptRoutedInput parent)
        {
            if (_lastButtonState == ButtonState.Pressed && eventArgs.MouseState.LeftButton == ButtonState.Released)
            {
                foreach (var item in parent.GetInputChildren())
                {
                    DoOnMouseLeftButtonUpCaptured(eventArgs, item);
                    if (eventArgs.IsHandled) break;
                    if (item == MouseManager.CaptureObject)
                    {
                        item.OnMouseLeftButtonUp(eventArgs);
                        if (eventArgs.IsHandled) break;
                    }

                }
            }

        }


        private void DoOnMouseMove(MouseRoutedEventArgs eventArgs, IAceeptRoutedInput parent)
        {
            foreach (var item in parent.GetInputChildren())
            {
                DoOnMouseMove(eventArgs, item);
                if (eventArgs.IsHandled) break;

                if (item.HitTest(eventArgs.MousePos))
                {
                    item.OnMouseMove(eventArgs);
                    if (eventArgs.IsHandled) break;
                }
            }
        }

        private void DoOnMouseMoveCaptured(MouseRoutedEventArgs eventArgs, IAceeptRoutedInput parent)
        {
            foreach (var item in parent.GetInputChildren())
            {
                DoOnMouseMoveCaptured(eventArgs, item);
                if (eventArgs.IsHandled) break;

                if (item == MouseManager.CaptureObject)
                {
                    item.OnMouseMove(eventArgs);
                    if (eventArgs.IsHandled) break;
                }
            }
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            //_spriteBatch.Begin();
            //_spriteBatch.Draw(_testImageTexture, Vector2.Zero, Color.White);
            //_spriteBatch.End();
            base.Draw(gameTime);
        }

        public void HandleInputReverse(RoutedEventArgs eventArgs)
        {

        }

        public void HandleInput(RoutedEventArgs eventArgs)
        {

        }

        public IEnumerable<IAceeptRoutedInput> GetInputChildren()
        {
            return Components.OfType<IAceeptRoutedInput>();
        }

        public void OnMouseLeftButtonDown(MouseRoutedEventArgs eventArgs)
        {

        }

        public void OnMouseLeftButtonUp(MouseRoutedEventArgs eventArgs)
        {

        }

        public void OnMouseMove(MouseRoutedEventArgs eventArgs)
        {

        }

        public bool HitTest(Vector2 mousePos)
        {
            return true;
        }
    }
}
